home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
ip
/
ka9q
/
src890906.arc
/
PC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-08-19
|
8KB
|
390 lines
/* OS- and machine-dependent stuff for IBM-PC running MS-DOS and Turbo-C */
#include <stdio.h>
#include <dir.h>
#include <dos.h>
#include <io.h>
#include <sys/stat.h>
#include <string.h>
#include <process.h>
#include <fcntl.h>
#include <alloc.h>
#include "global.h"
#include "mbuf.h"
#include "internet.h"
#include "iface.h"
#include "cmdparse.h"
#include "pc.h"
#include "proc.h"
static int kbchar __ARGS((void));
static void kbint __ARGS((void));
unsigned _stklen = 8192;
int Tick;
/* This flag is set by setirq() if IRQ 8-15 is used, indicating
* that the machine is a PC/AT with a second 8259 interrupt controller.
* If this flag is set, the interrupt return code in pcgen.asm will
* send an End of Interrupt command to the second 8259 as well as the
* first.
*/
char Isat;
/* Interface list header */
struct iface *Ifaces;
static char Ttbuf[BUFSIZ];
static int saved_break;
/* Keyboard input buffer */
#define KBSIZE 256
static struct {
char buf[KBSIZE];
char *wp;
char *rp;
int cnt;
} Keyboard;
int
errhandler(errval,ax,bp,si)
int errval,ax,bp,si;
{
return 3; /* Fail the system call */
}
/* Called at startup time to set up console I/O, memory heap */
void
ioinit(mem)
int32 mem;
{
#ifndef __TURBOC__
struct sgttyb ttybuf;
#endif
/* Ignore ctrl-breaks */
setvect(0x23,nullvec);
/* Fail all I/O errors */
harderr(errhandler);
/* Save these two file table entries for something more useful */
fclose(stdaux);
#ifdef __TURBOC__
fclose(stdprn);
#else
fclose(stdprt);
#endif
/* Interrupts use a special stack deep in data space.
* Calls to sbrk() (invoked by malloc when it needs more memory
* from the system) at interrupt time will fail because sbrk()
* will think that the stack has overwritten the heap. So
* grab all the memory we can now for the heap so that malloc
* won't have to call sbrk and alloc_mbuf() won't fail unnecessarily
* at interrupt time.
*/
#ifdef LARGEDATA
grabcore(mem);
#else
grabcore(mem);
#endif
setbuf(stdout,Ttbuf);
#ifdef __TURBOC__
saved_break = getcbrk();
setcbrk(0);
ioctl(fileno(stdout), 1, ioctl(fileno(stdout), 0) & 0xff | 0x20); /* put stdout in raw mode */
#else
/* Put display in raw mode. Note that this breaks tab expansion,
* so you need to run NANSI.SYS or equivalent.
*/
ioctl(1,TIOCGETP,&ttybuf);
ttybuf.sg_flags = RAW;
ioctl(1,TIOCSETP,&ttybuf);
#endif
/* Link timer handler into timer interrupt chain */
chtimer(btick);
/* Find out what multitasker we're running under, if any */
chktasker();
/* Initialize keyboard queue */
Keyboard.rp = Keyboard.wp = Keyboard.buf;
}
/* Called just before exiting to restore console state */
void
iostop()
{
#ifndef __TURBOC__
struct sgttyb ttybuf;
#endif
setbuf(stdout,NULLCHAR);
#ifdef __TURBOC__
setcbrk(saved_break);
ioctl(fileno(stdout), 1, ioctl(fileno(stdout), 0) & 0xff & ~0x20); /* put stdout in cooked mode */
#else
ioctl(1,TIOCGETP,&ttybuf);
ttybuf.sg_flags &= ~RAW;
ioctl(1,TIOCSETP,&ttybuf);
#endif
while(Ifaces != NULLIF){
if(Ifaces->stop != NULLFP)
(*Ifaces->stop)(Ifaces);
Ifaces = Ifaces->next;
}
/* Unlink timer handler from timer chain */
uchtimer();
}
/* Spawn subshell */
int
doshell(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char *command;
int ret;
#ifdef __TURBOC__
ioctl(fileno(stdout), 1, ioctl(fileno(stdout), 0) & 0xff & ~0x20); /* put stdout in cooked mode */
if((command = getenv("COMSPEC")) == NULLCHAR)
command = "/COMMAND.COM";
ret = spawnv(P_WAIT,command,argv);
ioctl(fileno(stdout), 1, ioctl(fileno(stdout), 0) & 0xff | 0x20); /* put stdout in raw mode */
return ret;
#else
struct sgttyb ttybuf,ttysav;
ioctl(1,TIOCGETP,&ttysav);
ioctl(1,TIOCGETP,&ttybuf);
ttybuf.sg_flags &= ~RAW;
ioctl(1,TIOCSETP,&ttybuf);
if((command = getenv("COMSPEC")) == NULLCHAR)
command = "/COMMAND.COM";
ret = fexecl(command,command,NULLCHAR);
ioctl(1,TIOCSETP,&ttysav);
if(ret == -1)
return -1;
else
return wait();
#endif
}
/* Keyboard interrupt handler */
static void
kbint()
{
int sig = 0;
int c;
while((c = kbraw()) != -1 && Keyboard.cnt < KBSIZE){
sig = 1;
*Keyboard.wp++ = c;
if(Keyboard.wp == &Keyboard.buf[KBSIZE])
Keyboard.wp = Keyboard.buf;
Keyboard.cnt++;
}
if(sig){
psignal(&Keyboard,1);
}
}
static int
kbchar()
{
char i_state;
char c;
i_state = dirps();
while(Keyboard.cnt == 0)
pwait(&Keyboard);
c = *Keyboard.rp++;
if(Keyboard.rp == &Keyboard.buf[KBSIZE])
Keyboard.rp = Keyboard.buf;
Keyboard.cnt--;
restore(i_state);
return c;
}
/* Read characters from the keyboard, translating them to "real" ASCII.
* If none are ready, block. The F-10 key is special; translate it to -2.
*/
int
kbread()
{
int c;
if((c = kbchar()) == 0){
/* Lead-in to a special char */
c = kbchar();
switch(c){
case 3: /* NULL (bizzare!) */
c = 0;
break;
case 68: /* F-10 key (used as command-mode escape) */
c = -2;
break;
case 83: /* DEL key */
c = 0x7f;
break;
default: /* Dunno what it is */
c = -1;
}
}
return c;
}
/* Called from the timer routine on each tick */
void
systick()
{
/* Tickle the keyboard interrupt. This nonsense is
* necessary because there's no way to get a hardware interrupt
* from the BIOS.
*/
kbint();
/* Flush out console. This gains efficiency in telnet
* since it only handles a character at a time, at the cost
* of a slight echo delay.
*/
fflush(stdout);
}
/* Install hardware interrupt handler.
* Takes IRQ numbers from 0-7 (0-15 on AT) and maps to actual 8086/286 vectors
* Note that bus line IRQ2 maps to IRQ9 on the AT
*/
int
setirq(irq,handler)
unsigned irq;
INTERRUPT (*handler)();
{
/* Set interrupt vector */
if(irq < 8){
setvect(8+irq,handler);
} else if(irq < 16){
Isat = 1;
setvect(0x70 + irq - 8,handler);
} else {
return -1;
}
return 0;
}
/* Return pointer to hardware interrupt handler.
* Takes IRQ numbers from 0-7 (0-15 on AT) and maps to actual 8086/286 vectors
*/
INTERRUPT
(*getirq(irq))()
unsigned int irq;
{
/* Set interrupt vector */
if(irq < 8){
return getvect(8+irq);
} else if(irq < 16){
return getvect(0x70 + irq - 8);
} else {
return NULLVIFP;
}
}
/* Disable hardware interrupt */
int
maskoff(irq)
unsigned irq;
{
if(irq < 8){
setbit(0x21,(char)(1<<irq));
} else if(irq < 16){
irq -= 8;
setbit(0xa1,(char)(1<<irq));
} else {
return -1;
}
return 0;
}
/* Enable hardware interrupt */
int
maskon(irq)
unsigned irq;
{
if(irq < 8){
clrbit(0x21,(char)(1<<irq));
} else if(irq < 16){
irq -= 8;
clrbit(0xa1,(char)(1<<irq));
} else {
return -1;
}
return 0;
}
/* Return 1 if specified interrupt is enabled, 0 if not, -1 if invalid */
int
getmask(irq)
unsigned irq;
{
if(irq < 8)
return (inportb(0x21) & (1 << irq)) ? 0 : 1;
else if(irq < 16){
irq -= 8;
return (inportb(0xa1) & (1 << irq)) ? 0 : 1;
} else
return -1;
}
/* Called from assembler stub linked to BIOS interrupt 1C, called on each
* hardware clock tick. Signal a clock tick to the timer process.
*/
void
ctick()
{
Tick++;
psignal(&Tick,1);
}
/* Set bit(s) in I/O port */
void
setbit(port,bits)
unsigned port;
char bits;
{
outportb(port,(char)inportb(port)|bits);
}
/* Clear bit(s) in I/O port */
void
clrbit(port,bits)
unsigned port;
char bits;
{
outportb(port,(char)(inportb(port) & ~bits));
}
/* Convert a pointer to a long integer */
long
ptol(p)
void *p;
{
long x;
x = FP_OFF(p);
#ifdef LARGEDATA
x |= (long)FP_SEG(p) << 16;
#endif
return x;
}
void *
ltop(l)
long l;
{
register unsigned seg,offset;
seg = l >> 16;
offset = l;
return MK_FP(seg,offset);
}
void
sysreset()
{
void (*foo) __ARGS((void));
foo = MK_FP(0xffff,0); /* FFFF:0000 is hardware reset vector */
(*foo)();
}